home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * B G . C
- * O.F.Ransen: 21st June 1991
- * This version: 27th April 1994
- *
- *
- */
-
- #include "comp.h"
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <conio.h>
- #include <time.h>
- #include "bg.h"
- #include "mousy.h"
-
- FILE* Rec_File = NULL ;
- boolean Debugging = FALSE ; /* If writing moves to a file */
- boolean Genetics = FALSE ; /* If doing Darwininian selection */
- boolean F10_Hit = FALSE ; /* Recieves F10 key from anywhere */
-
- extern Stats_t Statistics [N_PLAYERS] ;
- extern int Target_Score ;
-
- /*************************************************************************/
-
- static void Open_Record_File (ushort n) ;
- static void Swap_Players (Player_t* Pa, Player_t* Pb) ;
- static void Command_Line_Read (int argc, char* argv[]) ;
- static void Update_Score (Player_t Player, int Points) ;
- static boolean Game_Over (Player_t Human) ;
-
- /*************************************************************************/
-
- void main (int argc, char* argv[])
- {
- boolean Running ;
- Speed_t Speed ;
- short Opponent ;
- Player_t Human ; /* WHITE_PLAYER or BLACK_PLAYER */
-
- Check_Mouse () ;
- Command_Line_Read (argc,argv) ;
-
- Set_Ctl_C_Handler () ;
-
- Decode_And_Show_Titles () ;
- Print_Message (HAKTOC_MSG) ;
- (void)Get_Key() ;
-
- Init_Stats () ;
- Init_Rannum_Gen () ;
- Init_Graphics () ;
- Start_Up_Mouse () ;
- Randomise () ;
-
- if (Genetics) {
- Genetic_Selection () ;
- } else {
- Opponent = SERGIO ;
- Human = BLACK_PLAYER ;
- Speed = SLOW_SPEED ;
-
- Running = First_Interaction (&Speed,&Human,&Opponent) ;
-
- while (Running) {
- boolean Playing ;
- Init_Stats () ;
- Playing = TRUE ;
- while (Playing) {
- Print_Players (Opponent,Human) ;
- Playing = Play_The_Game (Speed,Human,Opponent) ;
- }
- Running = Top_Level_Interact (&Speed,&Human,&Opponent) ;
- }
- }
- Go_Text_Mode () ;
- Show_Titles () ;
- }
-
- /*************************************************************************/
-
- boolean Play_The_Game (Speed_t Speed, Player_t Human, short O_Index)
- /*
- PURPOSE: To play a single game of backgammon, returning TRUE while
- the target score has not been reached. We return FALSE when
- the target score has been reached or when the user hits F10.
- NOTES: 2) If Human!=NULL_PLAYER then the Human is either red or
- white and wants to play against the computer.
- */
- {
- Layout_t Curr_Lay[2] ; /* The current layouts */
- Transit_t Transit[2] ; /* The new layouts and how we got there */
- Player_t Opponent,Player,Starter ;
- boolean First_Loop, /* Dice already thrown, just move */
- Finished, /* Game over */
- Can_Move, /* Move possible with these dice */
- Doubled, /* Current player doubled stakes */
- Rejected ; /* Current opponent rejected stakes */
- extern Player_t Double_Possessor ;
- extern int Double_Value ;
- extern int N_Moves ;
- Dice_t Dice ;
- char User_Char ;
- short Points ;
-
- if (Debugging) {
- Open_Record_File (0) ;
- }
-
- #if DRODBAR
- Test_Move () ;
- #endif
-
- N_Moves = 0 ; // Helps to decide when to double
- Double_Value = 1 ; /* No double yet */
- Double_Possessor = NULL_PLAYER ;
-
- Initial_Board (Curr_Lay) ;
- Draw_Board_Full (Curr_Lay) ;
-
- if (!Genetics) {
- Show_Opponents_Face (Curr_Lay,Human,O_Index) ;
- Draw_Eyes (2,O_Index) ;
- }
-
- Select_Starter (&Starter,&Dice) ;
- if (F10_Hit) {
- F10_Hit = FALSE ;
- return (F10_KEY) ;
- }
- Player = Starter ;
- Opponent = OPPONENT(Starter) ;
- First_Loop = TRUE ; /* So we don't throw the dice again */
-
- Finished = FALSE ;
- User_Char = 0 ; /* Not Escape yet */
- Print_Message (HELP_MSG) ;
-
- do {
- if (!First_Loop) {
- /* Have to throw the dice */
- if (Move_Possible (Curr_Lay[Player],Curr_Lay[Opponent])) {
- /* It is worth throwing the dice */
- Dice = Throw_Dice (Player,Opponent,Human,&Doubled,&Rejected,Curr_Lay) ;
- if (F10_Hit) {
- F10_Hit = FALSE ;
- return (FALSE) ;
- }
- if (Doubled && Rejected) {
- /* Opponent rejected the double, so Player wins */
- Update_Score (Player,1) ;
- Show_Winner (Player,Human,1) ;
- Finished = TRUE ;
- Can_Move = FALSE ;
- /*
- * See if we have finished the whole set.
- */
- if (Game_Over (Human)) {
- return (FALSE) ;
- } else {
- User_Char = (char)Key_And_Delay (3) ; /* Wait a bit */
- return (User_Char != F10_KEY) ;
- }
- } else {
- Draw_Dice_Pair (&Dice,Player) ;
- if (!Genetics) {
- Draw_Eyes (Dice.N_Vals,O_Index) ;
- }
- Can_Move = TRUE ;
- }
- } else {
- /* Move is not possible */
- if (Player == WHITE_PLAYER) {
- Print_Message (W_NOGO_MSG) ;
- } else {
- Print_Message (B_NOGO_MSG) ;
- }
- Seconds_Delay (2) ;
- Swap_Players (&Player,&Opponent) ;
- Finished = FALSE ;
- Can_Move = FALSE ;
- }
- } else {
- /* Dice already thrown for us */
- Can_Move = TRUE ;
- First_Loop = FALSE ;
- }
-
- if (Can_Move) {
- Draw_Stats () ;
- if (Player == Human) {
- User_Char = User_Selects_Move (&Dice,
- Curr_Lay [Player], Curr_Lay [Opponent],
- &Transit [Player], &Transit [Opponent],
- Player) ;
- if (User_Char == F10_KEY) {
- F10_Hit = FALSE ;
- return (FALSE) ;
- }
- } else {
- if (Human != NULL_PLAYER) {
- Seconds_Delay (2) ; /* So man can sees computers dice */
- }
- Select_Best_Move (&Dice,
- Curr_Lay [Player], Curr_Lay [Opponent],
- &Transit [Player], &Transit [Opponent],
- Player,Bestest) ;
- }
-
- Copy_Layout (Curr_Lay [Player], Transit[Player].Layout) ;
- Copy_Layout (Curr_Lay [Opponent],Transit[Opponent].Layout) ;
- if (!Genetics) {
- Show_Opponents_Face (Curr_Lay,Human,O_Index) ;
- }
-
- if (Player != Human) {
- /* Show the human how the computer moved */
- User_Char = Show_Transits_And_Kb_Look (&Transit [Player],
- &Transit [Opponent],
- Player,Speed) ;
- Draw_Board_Quick (Curr_Lay[BLACK_PLAYER],Curr_Lay[WHITE_PLAYER]) ;
- }
-
- if (Debugging) {
- Record_Move (Player,&Dice,Curr_Lay[BLACK_PLAYER],Curr_Lay[WHITE_PLAYER]) ;
- }
-
- Finished = (User_Char == F10_KEY) ;
- Points = Won (Curr_Lay[Player],Curr_Lay[Opponent]) ;
- if (Points > NO_WIN) {
- Update_Score (Player,Points) ;
- Show_Winner (Player,Human,Points) ;
- Finished = TRUE ;
- /*
- * See if we have finished the whole set.
- */
- if (Game_Over (Human)) {
- return (FALSE) ;
- } else {
- User_Char = (char)Key_And_Delay (2) ;
- return (User_Char != F10_KEY) ;
- }
- } else {
- Swap_Players (&Player,&Opponent) ;
- }
- }
- N_Moves++ ;
- } while (!Finished) ;
-
- if (Debugging) {
- fclose (Rec_File) ;
- Rec_File = NULL ;
- }
-
- return (User_Char != F10_KEY) ;
- }
-
- /*************************************************************************/
-
- void Select_Starter (Player_t* Player, Dice_t* Dice)
- /*
- PURPOSE: To select who will start the game, with graphics. We return who
- starts the game in Player, and the dice with which he starts in Dice.
- */
- {
- int Black_Score,White_Score,Rand_Rolls,r ;
- extern Throw_t Throw ;
- Dice_t Temp_Dice ;
-
- if (Throw == MANUAL_THROW) {
- do {
- Temp_Dice = Human_Throws_Dice (BLACK_PLAYER,WHITE_PLAYER) ;
- if (F10_Hit) {
- return ;
- }
- } while (Temp_Dice.Values[0] == Temp_Dice.Values[1]) ;
-
- Copy_Dice (Dice,&Temp_Dice) ;
- Black_Score = Temp_Dice.Values[BLACK_PLAYER] ;
- White_Score = Temp_Dice.Values[WHITE_PLAYER] ;
- } else {
- do {
- if (Genetics) {
- Rand_Rolls = 1 ;
- } else {
- Rand_Rolls = Int_Rand_Range (MIN_ROLLS,MAX_ROLLS) ;
- }
- for (r = 0 ; r < Rand_Rolls ; r++) {
- Black_Score = Int_Rand_Range (1,6) ;
- White_Score = Int_Rand_Range (1,6) ;
- Draw_Die (Black_Score,1,BLACK_PLAYER) ;
- Draw_Die (White_Score,2,WHITE_PLAYER) ;
- }
- Seconds_Delay (3) ;
- } while (Black_Score == White_Score) ;
-
- Dice->N_Vals = 2 ;
- Dice->Values[0] = (char)Black_Score ;
- Dice->Values[1] = (char)White_Score ;
- }
-
- if (Black_Score > White_Score) {
- (*Player) = BLACK_PLAYER ;
- } else {
- (*Player) = WHITE_PLAYER ;
- }
-
- /* Update the dice statistics of the winning player */
- Statistics [(*Player)].N_Throws++ ;
- Statistics [(*Player)].Total += (Black_Score + White_Score) ;
- }
-
- /*************************************************************************/
-
- void Seconds_Delay (short seconds)
- /* PURPOSE: Guess. */
- {
- time_t Then, Now ;
-
- if (Genetics) {
- return ; // Go as fast as you can!
- }
-
- (void)time (&Then) ;
- do {
- (void)time (&Now) ;
- } while ((Now - Then) < seconds) ;
- }
-
- /***************************************************************************/
-
- void Record_Move (Player_t Player, Dice_t* Dice,
- Layout_t Black, Layout_t White)
- /*
- PURPOSE: To file the move in the global Rec_File.
- */
- {
- short d ;
-
- if (Rec_File == NULL) {
- Error_Exit ("Writing to NULL Rec_File") ;
- }
-
- fprintf (Rec_File,"\nDice_t = ") ;
-
- fprintf (Rec_File,"{%1d,{",Dice->N_Vals) ;
- for (d=0 ; d < MAX_MOVES-1 ; d++) {
- fprintf (Rec_File,"%1d,",Dice->Values[d]) ;
- }
- fprintf (Rec_File,"%1d}} ; ",Dice->Values[d]) ;
- if (Player == BLACK_PLAYER) {
- fprintf (Rec_File,"/* BLACK */") ;
- } else {
- fprintf (Rec_File,"/* WHITE */") ;
- }
-
- Print_Layouts (Black,White) ;
-
- fprintf (Rec_File,"\n") ;
- }
-
- /***************************************************************************/
-
- void Print_Layouts (Layout_t Black, Layout_t White)
- /*
- PURPOSE: A debugging printout of the board into the Rec_File
- */
- {
- Print_Layout (White,WHITE_PLAYER) ;
- Print_Layout (Black,BLACK_PLAYER) ;
- }
-
- /*************************************************************************/
-
- void Print_Layout (Layout_t Layout, Player_t Player)
- /*
- PURPOSE: To print the layout in an easily machine and human readable form.
- */
- {
- ushort p,o,r ;
-
- if (Player == BLACK_PLAYER) {
- fprintf (Rec_File,"\n\nLayout_t Black_Lay = {") ;
- } else {
- fprintf (Rec_File,"\n\nLayout_t White_Lay = {") ;
- }
-
- fprintf (Rec_File,"%2d, /* BAR_I */ ",Layout[BAR_I]) ;
- for (r = 0 ; r < 4 ; r++) {
- o = r*6 ;
- fprintf (Rec_File,"\n ") ;
- for (p = 1 ; p <= 6 ; p++) {
- fprintf (Rec_File,"%2d,",Layout[o+p]) ;
- }
- }
- fprintf (Rec_File,"\n %2d}; /* HOME_I*/ ",
- Layout[HOME_I]) ;
- }
-
- /*************************************************************************/
-
- #if DRODBAR
- Dice_t Test_Dice = {4,{3,3,3,3}} ; /* New layouts = */
-
- Layout_t White_Lay = { 0, /* BAR_I */
- 0, 0, 0, 3, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
- 2, 0, 0, 0, 0, 3,
- 7}; /* HOME_I*/
-
- Layout_t Black_Lay = { 0, /* BAR_I */
- 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 3,
- 0, 0, 0, 0, 0, 0,
- 5, 2, 0, 0, 0, 0,
- 4}; /* HOME_I*/
-
-
- void Test_Move (void)
- /*
- PURPOSE: To see how and why the computer moves as he did...
- */
- {
- Player_t Player,Opponent ;
- Layout_t Curr_Lay[2] ; /* The current layouts */
- Transit_t Transit[2] ; /* The new layouts and how we got there */
-
- Copy_Layout (Curr_Lay[BLACK_PLAYER],Black_Lay) ;
- Copy_Layout (Curr_Lay[WHITE_PLAYER],White_Lay) ;
-
- Player = WHITE_PLAYER ;
- Opponent = BLACK_PLAYER ;
-
- Draw_Board_Full (Curr_Lay) ;
- Draw_Dice_Pair (&Test_Dice,Player) ;
-
- (void)User_Selects_Move (&Test_Dice,
- Curr_Lay [Player], Curr_Lay [Opponent],
- &Transit [Player], &Transit [Opponent],
- Player) ;
- Show_Transits_And_Kb_Look (&Transit [Player],
- &Transit [Opponent],
- Player,PAUSING) ;
- Draw_Board_Quick (Curr_Lay[BLACK_PLAYER],Curr_Lay[WHITE_PLAYER]) ;
- Error_Exit ("") ;
- }
-
- /*************************************************************************/
- #endif
- /*************************************************************************/
-
- static void Open_Record_File (ushort n)
- /*
- PURPOSE: To open a file to record the moves of the nth game. The name
- is based on the number.
- */
- {
- char Num_Str[8], Name[16] ;
-
- sprintf (Num_Str,"%d",n) ;
- (void)strcpy (Name,"BG") ;
- (void)strcat (Name,Num_Str) ;
- (void)strcat (Name,".REC") ;
-
- Rec_File = fopen (Name,"w") ; /* Write Text File */
- if (Rec_File == NULL) {
- Error_Exit ("Cannot open record file") ;
- }
- fprintf (Rec_File,"\n/* SEQUENCE OF MOVES, %s */\n",VER_STR) ;
- }
-
- /*************************************************************************/
-
- void Swap_Players (Player_t* Pa, Player_t* Pb)
- /* Swap the two players */
- {
- Player_t Temp ;
- Temp = (*Pa) ;
- (*Pa) = (*Pb) ;
- (*Pb) = Temp ;
- }
-
- /*************************************************************************/
-
- /* The options type, a command line option and the address of the
- boolean it affects */
-
- #define N_OPTIONS 4
-
- typedef struct {
- char Name[20] ;
- boolean* Adr ;
- } Opt_t ;
-
- extern boolean Force_BW ;
-
- static Opt_t Options [N_OPTIONS] = {
- {"debug", &Debugging}, /* Writes all moves to a file */
- {"genetics",&Genetics}, /* All-Computer tournament, no interaction */
- {"mono", &Force_BW}} ; /* Forces black and white display */
-
- static void Command_Line_Read (int argc, char* argv[])
- /*
- PURPOSE: To see if the user has typed any special command line
- options, and to set the options accordingly.
- */
- {
- short a,o ;
-
- for (a = 0 ; a < argc ; a++) {
- for (o = 0 ; o < N_OPTIONS ; o++) {
- if (strcmpi (argv[a],Options[o].Name) == SAME_STRING) {
- (*Options[o].Adr) = TRUE ;
- }
- }
- }
- }
-
- /*************************************************************************/
-
- static void Update_Score (Player_t Player, int Points)
- /*
- PURPOSE: To update the stats for the player, display them, and set
- No_Cube to the correct value.
- */
- {
- extern int Double_Value ;
- extern int Target_Score ;
- extern boolean No_Cube ;
-
- Statistics[Player].Games_Won+= (Double_Value*Points) ;
- Draw_Stats () ;
-
- if (!No_Cube) {
- /* Either before or after freeze */
- if (Statistics[BLACK_PLAYER].Games_Won != Statistics[WHITE_PLAYER].Games_Won) {
- if (Statistics[Player].Games_Won == (Target_Score-1)) {
- Print_Message (NO_CUBE_MSG) ;
- No_Cube = TRUE ;
- } else {
- No_Cube = FALSE ;
- }
- } else {
- No_Cube = FALSE ;
- }
- } else {
- /* It has been TRUE, it last for one game only */
- No_Cube = FALSE ;
- }
- }
-
- /*************************************************************************/
-
- static boolean Game_Over (Player_t Human)
- /*
- PURPOSE: To return TRUE if the whole set of matches is finished.
- If the Human is playing then we write some messages for him too.
- */
- {
- if (Human != NULL_PLAYER) {
- if (Statistics[OPPONENT(Human)].Games_Won >= Target_Score) {
- Print_Message (COM_WINS_SET_MSG) ;
- Seconds_Delay (2) ;
- return (TRUE) ;
- } else if (Statistics[Human].Games_Won >= Target_Score) {
- Print_Message (YOU_WIN_SET_MSG) ;
- Seconds_Delay (2) ;
- return (TRUE) ;
- } else {
- return (FALSE) ;
- }
- } else {
- if (Statistics [BLACK_PLAYER].Games_Won >= Target_Score) {
- return (TRUE) ;
- } else if (Statistics [WHITE_PLAYER].Games_Won >= Target_Score) {
- return (TRUE) ;
- } else {
- return (FALSE) ;
- }
- }
- }
-
- /*************************************************************************/
-